// 接口类型

// package main

// type Animal interface {
// 	Name() string
// 	Speak() string
// }

// type Cat struct {
// }

// func (cat Cat) Name() string {
// 	return "Cat"
// }

// func (cat Cat) Speak() string {
// 	return "喵喵喵"
// }

// func main() {

// }

// 接口的创建和实现
// package main

// import (
// 	"errors"
// 	"fmt"
// )

// type IDatabaser interface {
// 	Connect() error
// 	Disconnect() error
// }

// // mysql 操作
// type Mysql struct {
// 	DBName    string
// 	isConnect bool
// }

// func (mysql *Mysql) Connect() error {
// 	fmt.Println("Mysql Connect DB => " + mysql.DBName)
// 	mysql.isConnect = true
// 	if mysql.isConnect {
// 		fmt.Println("Mysql Connect Success")
// 		return nil
// 	} else {
// 		return errors.New("Connect failure!")
// 	}
// }

// func (mysql *Mysql) Disconnect() error {
// 	fmt.Println("Mysql Disconnect Success!")
// 	return nil
// }

// type Redis struct {
// 	DBName string
// }

// type IRediser interface {
// 	Connect() error
// }

// func (redis *Redis) Connect() error {
// 	fmt.Println("Redis Connect DB => " + redis.DBName)
// 	fmt.Println("Redis Connect Success!")
// 	return nil
// }

// func (redis *Redis) Disconnect() error {
// 	fmt.Println("Redis Disconnect Success!")
// 	return nil
// }

// func HandleDB(db IDatabaser) {
// 	fmt.Println("start link")
// 	db.Connect()
// 	fmt.Println("close link")
// 	db.Disconnect()
// }

// func main() {
// 	// var mysql = Mysql{DBName: "student"}
// 	// fmt.Println("start link")
// 	// mysql.Connect()

// 	// var redis = Redis{DBName: "teacher"}
// 	// fmt.Println("start link")
// 	// redis.Connect()
// 	// fmt.Println("close link")
// 	// redis.Disconnect()

// 	// 抽象出连接数据库逻辑
// 	// var mysql = Mysql{DBName: "student"}
// 	// HandleDB(&mysql)
// 	// var redis = Redis{DBName: "teacher"}
// 	// HandleDB(&redis)

// 	// 接口赋值
// 	// var redis = Redis{DBName: "teacher"}
// 	// var idb IDatabaser = &redis
// 	// idb.Connect()
// 	// idb.Disconnect()

// 	// 接口赋值2
// 	var idb IDatabaser = &Redis{DBName: "teacher"}
// 	var iredis IRediser
// 	iredis = idb
// 	iredis.Connect()

// }

// 接口嵌入 即接口组合 继承
// 一个接口类型只接受其他的接口类型的嵌入， 嵌入结构体或其他类型会报错
// 一个接口类型不能嵌入自身，包括直接和间接嵌入

// package main

// import "fmt"

// type IPerson interface {
// 	Speak()
// }

// type IStudent interface {
// 	IPerson
// 	Study()
// }

// type ITeacher interface {
// 	IPerson
// 	Teach()
// }

// type Student struct {
// 	Name string
// }

// func (s *Student) Speack() {
// 	fmt.Println("My name is ", s.Name)
// }

// func (s *Student) Study() {
// 	fmt.Println(s.Name, "is studying")
// }

// type Teacher struct {
// 	Name string
// }

// func (t *Teacher) Speak() {
// 	fmt.Println("My name is ", t.Name)
// }

// func (t *Teacher) Teache() {
// 	fmt.Println(t.Name, "is teaching")
// }

// func (t IPerson) Speak() {
// 	fmt.Println("My name is ", t.Name)
// }

// func main() {
// 	var stu Student = Student{"Xiao Ming"}
// 	var teacher Teacher = Teacher{"Mr.Li"}

// 	stu.Speack()
// 	stu.Study()
// 	teacher.Speak()
// 	teacher.Teache()
// }

package main

import "fmt"

type IPerson interface {
	Speak()
	Study()
	Teach()
}

type Student interface {
	Speak()
	Study()
}

type Teacher interface {
	Speak()
	Teach()
}

type Person struct {
	Name string
}

func (s *Person) Speak() {
	fmt.Println("My name is ", s.Name)
}

func (s *Person) Study() {
	fmt.Println(s.Name, "is studying")
}

func (t *Person) Teach() {
	fmt.Println(t.Name, "is teaching")
}

func main() {
	var stu Student = &Person{"Xiao Ming"}
	var teacher Teacher = &Person{"Mr.Li"}

	stu.Speak()
	stu.Study()
	teacher.Speak()
	teacher.Teach()
}

// 空接口 go语言中最特殊的接口 空接口不包含任何方法， 所有类型都实现了空接口， 因此空接口可以存储 任意类型的数值

// package main

// import (
// 	"fmt"
// 	"strconv"
// )

// func Log(name string, i interface{}) {
// 	fmt.Printf("Name =%s, Type= %T, value=%v\n", name, i, i)
// 	fmt.Printf("\n")
// }

// func main() {
// 	var v1 interface{} = 1
// 	var v2 interface{} = "abc"
// 	var v3 interface{} = true
// 	var v4 interface{} = &v1
// 	var v5 interface{} = struct {
// 		Name string
// 	}{"Xiao Ming"}
// 	var v6 interface{} = &v5
// 	list_v := []interface{}{v1, v2, v3, v4, v5, v6}
// 	for index, val := range list_v {
// 		fmt.Println("v" + strconv.Itoa(index))
// 		Log(fmt.Sprintf("v%v", index), val)
// 	}
// }

// 从空接口取值
// package main

// import "fmt"

// func main() {
// 	var a string = "abc"
// 	var i interface{} = a
// 	var b string = i.(string) // need type assertion
// 	fmt.Println(b)
// }

// 空接口的常见使用
// package main

// import "fmt"

// func Log(args ...interface{}) {
// 	for num, arg := range args {
// 		fmt.Printf("Index => %d, Value => %v\n", num, arg)
// 	}
// }

// func main() {
// 	// s := make([]interface{}, 3)
// 	// s[0] = 1
// 	// s[1] = "abc"
// 	// s[2] = struct {
// 	// 	Num int
// 	// }{1}

// 	s := []interface{}{
// 		1,
// 		"abc",
// 		struct {
// 			Num int
// 		}{1},
// 	}

// 	// 可变长参数
// 	fmt.Println("===将切片拆散===")
// 	Log(s...)
// 	fmt.Println("===直接传入切片===")
// 	Log(s)

// }

// 类型断言
// package main

// import "fmt"

// func checkType(t interface{}, ok bool) {
// 	if ok {
// 		fmt.Println("断言成功")
// 	} else {
// 		fmt.Println("断言失败")
// 	}
// 	fmt.Printf("变量t的类型 =%T, 值 =%v \n", t, t)
// }

// func main() {
// 	var X interface{} = 1
// 	fmt.Println("第一次断言:")
// 	t0, ok := X.(string)
// 	checkType(t0, ok)
// 	fmt.Println("第二次断言:")
// 	t1, ok := X.(float64)
// 	checkType(t1, ok)
// 	fmt.Println("第三次断言:")
// 	t2, ok := X.(int)
// 	checkType(t2, ok)
// }

// package main

// import "fmt"

// type Person struct {
// 	Name string
// 	Age  int
// }

// func main() {
// 	s := make([]interface{}, 3)
// 	s[0] = 1
// 	s[1] = "str"
// 	s[2] = Person{"Peter", 23}
// 	for index, data := range s {
// 		switch value := data.(type) {
// 		case int:
// 			fmt.Printf("s[%d] Type= int, Value= %d\n", index, value)
// 		case string:
// 			fmt.Printf("s[%d] Type= string, Value= %s\n", index, value)
// 		case Person:
// 			fmt.Printf("s[%d] Type= Person Value= %v\n", index, value)
// 		default:
// 			fmt.Printf("s[%d] Type= interface, Value= %d\n", index, value)
// 		}
// 	}

// }

// package main

// import "fmt"

// type IPhoner interface {
// 	Call() error
// 	Video() error
// 	Game() error
// }

// type Apple interface {
// 	Call() error
// 	Video() error
// }

// type Huawei interface {
// 	Call() error
// 	Game() error
// }

// type Phone struct {
// 	Name string
// }

// func (p *Phone) Call() error {
// 	fmt.Println(p.Name, "start Call")
// 	return nil
// }

// func (p *Phone) Video() error {
// 	fmt.Println(p.Name, "Start Video")
// 	return nil
// }

// func (p *Phone) Game() error {
// 	fmt.Println(p.Name, "Start Game")
// 	return nil
// }

// func main() {
// 	var apple Apple = &Phone{"apple"}
// 	var huawei Huawei = &Phone{"huawei"}
// 	apple.Call()
// 	huawei.Game()
// }
